package com.happiness.base.intercept;

import cn.hutool.json.JSONUtil;
import com.happiness.base.annotation.WebResult;
import com.happiness.base.enums.RequestSourceEnums;
import com.happiness.base.enums.ResultCodeEnum;
import com.happiness.base.http.ResultInfo;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 全局统一响应处理
 * 重写返回体
 * */
@ControllerAdvice
public class ResponseResultInterceptor implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    // 判断是否请求包含了 包装注解标记，有则重写返回体
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(!(o instanceof ResultInfo)){
            HttpServletRequest request = attributes.getRequest();
            String header = request.getHeader(RequestSourceEnums.HTTP.header);
            if (Objects.isNull(header)){
                final Class<?> clazz = methodParameter.getMethod().getDeclaringClass();
                final Method method = methodParameter.getMethod();
                WebResult annotation = null;
                // 判断是否在方法上面加了注解
                if (method.isAnnotationPresent(WebResult.class)){
                    annotation = method.getAnnotation(WebResult.class);
                }else if (clazz.isAnnotationPresent(WebResult.class)){
                    annotation = clazz.getAnnotation(WebResult.class);
                }
                if (!Objects.isNull(annotation)){
                    ResultInfo resultInfo = new ResultInfo(ResultCodeEnum.SUCCESS, o);
                    //因为handler处理类的返回类型是String，为了保证一致性，这里需要将ResponseResult转回去
                    if(o instanceof String) {
                        return JSONUtil.toJsonStr(resultInfo);
                    }
                    return o;
                }
            }
        }else {
            ResultInfo resultInfo = (ResultInfo)o;
            if (!Objects.equals(resultInfo.getCode(),ResultCodeEnum.SUCCESS.code)){
                attributes.getResponse().setStatus(resultInfo.getCode());
            }
        }
        return o;
    }
}
